<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
  
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

  
  <link href="../css/style.css" rel="stylesheet" type="text/css">

</head>
<body>
<h1>4.10. Логические операции</h1>
<p class="article">
Логические операции выполняются поразрядно, то есть отдельно для каждого бита операндов. В результате выполнения изменяются флаги. В программах эти операции часто используются для сброса, установки или инверсии отдельных битов двоичных чисел.
</p>
<h2>Логическое И</h2>
<p class="article">
Если оба бита равны 1, то результат равен 1, иначе результат равен 0.
</p>
<table class="auto">
<tr align="center" valign="center">
	<td>AND</th>
	<td width="20">0</th>
	<td width="20">1</th>
</tr>
<tr align="center" valign="center">
	<td>0</th>
	<td>0</td>
	<td>0</td>
</tr>
<tr align="center" valign="center">
	<td>1</th>
	<td>0</td>
	<td>1</td>
</tr>
</table>
<p class="article">
Для выполнения операции логического И предназначена команда AND. У этой команды 2 операнда, результат помещается на место первого операнда. Часто эта команда используется для обнуления определённых битов числа. При этом второй операнд называют маской. Обнуляются те биты операнда, которые в маске равны 0, значения остальных битов сохраняются. Примеры:
</p>
<pre class="code">
and ax,bx           ;AX = AX & BX
    and cl,11111110b    ;Обнуление младшего бита CL
    and dl,00001111b    ;Обнуление старшей тетрады DL
</pre>
<p class="article">
Ещё одно использование этой команды — быстрое вычисление остатка от деления на степень 2. Например, так можно вычислить остаток от деления на 8:
</p>
<pre class="code">
    and ax,111b         ;AX = остаток от деления AX на 8
</pre>
<h2>Логическое ИЛИ</h2>
<p class="article">
Если хотя бы один из битов равен 1, то результат равен 1, иначе результат равен 0.
</p>
<table class="auto">
	<tr align="center" valign="center">
		<td>OR</th>
		<td width="20">0</th>
		<td width="20">1</th>
	</tr>
	<tr align="center" valign="center">
		<td>0</th>
		<td>0</td>
		<td>1</td>
	</tr>
	<tr align="center" valign="center">
		<td>1</th>
		<td>1</td>
		<td>1</td>
	</tr>
</table>
<p class="article">
Логическое ИЛИ вычисляется с помощью команды OR. У этой команды тоже 2 операнда, и результат помещается на место первого. Часто это команда используется для установки в 1 определённых битов числа. Если бит маски равен 1, то бит результата будет равен 1, остальные биты сохранят свои значения. <br /> Примеры:
</p>
<pre class="code">
    or al,dl            ;AL = AL | DL
    or bl,10000000b     ;Установить знаковый бит BL
    or cl,00100101b     ;Включить биты 0,2,5 CL
</pre>
<h2>Логическое НЕ (инверсия)</h2>
<p class="article">
Каждый бит операнда меняет своё значение на противоположное (0 → 1, 1 → 0). Операция выполняется с помощью команды NOT. У этой команды только один операнд. Результат помещается на место операнда. Эта команда не изменяет значения флагов. <br /> Пример:
</p>
<pre class="code">
    not byte[bx]        ;Инверсия байта по адресу в BX
</pre>
<h2>Логическое НЕ (инверсия)</h2>
<p class="article">
Каждый бит операнда меняет своё значение на противоположное (0 → 1, 1 → 0). Операция выполняется с помощью команды NOT. У этой команды только один операнд. Результат помещается на место операнда. Эта команда не изменяет значения флагов. <br /> Пример:
</p>
<pre class="code">
    not byte[bx]        ;Инверсия байта по адресу в BX
</pre>
<h2>Логическое исключающее ИЛИ (сумма по модулю два)</h2>
<p class="article">
Если биты имеют одинаковое значение, то результат равен 0, иначе результат равен 1.
</p>
<table class="auto">
	<tr align="center" valign="center">
		<td>XOR</th>
		<td width="20">0</th>
		<td width="20">1</th>
	</tr>
	<tr align="center" valign="center">
		<td>0</th>
		<td>0</td>
		<td>1</td>
	</tr>
	<tr align="center" valign="center">
		<td>1</th>
		<td>1</td>
		<td>0</td>
	</tr>
</table>
<p class="article">
Исключающим ИЛИ эта операция называется потому, что результат равен 1, если один бит равен 1 или другой равен 1, а случай, когда оба равны 1, исключается. Ещё эта операция напоминает сложение, но в пределах одного бита, без переноса. 1+1=10, но перенос в другой разряд игнорируется и получается 0, отсюда название «сумма по модулю 2». Для выполнения этой операции предназначена команда XOR. У команды два операнда, результат помещается на место первого. Команду можно использовать для инверсии определённых битов операнда. Инвертируются те биты, которые в маске равны 1, остальные сохраняют своё значение. Примеры:
</p>
<pre class="code">
    xor si,di           ;SI = SI ^ DI
    xor al,11110000b    ;Инверсия старшей тетрады AL
    xor bp,8000h        ;Инверсия знакового бита BP
</pre>
<p class="article">
Обозначение операции в комментарии к первой строке используется во многих языках высокого уровня (например C, C++, Java и т.д.). Часто XOR используют для обнуления регистров. Если операнды равны, то результат операции всегда равен 0. Такой способ обнуления работает быстрее и, в отличие от команды MOV, не содержит непосредственного операнда, поэтому команда получается короче. 
</p>
<pre class="code">
    mov bx,0            ;Эта команда занимает 3 байта
    xor bx,bx           ;А эта - всего 2
</pre>
<h2>Пример программы</h2>
<p class="article">
Допустим, у нас есть массив байтов. Размер массива хранится в байте без знака. Требуется в каждом байте сбросить 1-й и 5-й биты, установить 0-й и 3-й биты, инвертировать 7-й бит. А затем ещё инвертировать целиком последний байт массива.
</p>
<pre class="code">
use16                   ;Генерировать 16-битный код
org 100h                ;Программа начинается с адреса 100h
 
    mov bx,array        ;BX = адрес массива
    movzx cx,[length]   ;CX = длина массива
 
    mov di,cx
    dec di
    add di,bx           ;DI = адрес последнего элемента
m1:
    mov al,[bx]         ;AL = очередной элемент массива
    and al,11011101b    ;Сбрасываем 1-й и 5-й биты
    or  al,00001001b    ;Устанавливаем 0-й и 3-й биты
    xor al,10000000b    ;Инвертируем 7-й бит
    mov [bx],al         ;Сохраняем обработанный элемент
    inc bx              ;В BX - адрес следующего элемента
    loop m1             ;Команда цикла
 
    not byte[di]        ;Инвертируем последний байт массива
 
    mov ax,4C00h        ;\
    int 21h             ;/ Завершение программы
;----------------------------------------------------------
length  db 10
array   db 1,5,3,88,128,97,253,192,138,0
</pre>
</body>
</html>
